<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace core\http\bags;

/**
 * ResponseHeaderBag is a container for Response HTTP headers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
use core\http\Cookie;

class ResponseHeaderBag extends HeaderBag {
	protected $computedCacheControl = array();
	
	/**
	 * Constructor.
	 *
	 * @param array $headers An array of HTTP headers
	 */
	public function __construct(array $headers = array()) {
		parent::__construct( $headers );
		
		if( !isset( $this->headers['cache-control'] ) ) {
			$this->set( 'cache-control', '' );
		}
	}
	
	/**
	 * {@inheritdoc}
	 */
	public function replace(array $headers = array()) {
		parent::replace( $headers );
		
		if( !isset( $this->headers['cache-control'] ) ) {
			$this->set( 'cache-control', '' );
		}
	}
	
	/**
	 * {@inheritdoc}
	 */
	public function set($key, $values, $replace = true) {
		parent::set( $key, $values, $replace );
		
		// ensure the cache-control header has sensible defaults
		if( in_array( strtr( strtolower( $key ), '_', '-' ), array( 'cache-control', 'etag', 'last-modified', 'expires' ) ) ) {
			$computed = $this->computeCacheControlValue();
			$this->headers['cache-control'] = array( $computed );
			$this->computedCacheControl = $this->parseCacheControl( $computed );
		}
	}
	
	/**
	 * {@inheritdoc}
	 */
	public function remove($key) {
		parent::remove( $key );
		
		if( 'cache-control' === strtr( strtolower( $key ), '_', '-' ) ) {
			$this->computedCacheControl = array();
		}
	}
	
	/**
	 * {@inheritdoc}
	 */
	public function hasCacheControlDirective($key) {
		return array_key_exists( $key, $this->computedCacheControl );
	}
	
	/**
	 * {@inheritdoc}
	 */
	public function getCacheControlDirective($key) {
		return array_key_exists( $key, $this->computedCacheControl ) ? $this->computedCacheControl[$key] : null;
	}
	
	/**
	 * Clears a cookie in the browser
	 *
	 * @param string $name
	 * @param string $path
	 * @param string $domain
	 * @return void
	 */
	public function clearCookie($name, $path = null, $domain = null) {
		$this->setCookie( new Cookie( $name, null, 1, $path, $domain ) );
	}
	
	/**
	 * Returns the calculated value of the cache-control header.
	 *
	 * This considers several other headers and calculates or modifies the
	 * cache-control header to a sensible, conservative value.
	 *
	 * @return string
	 */
	protected function computeCacheControlValue() {
		if( !$this->cacheControl && !$this->has( 'ETag' ) && !$this->has( 'Last-Modified' ) && !$this->has( 'Expires' ) ) {
			return 'no-cache';
		}
		
		if( !$this->cacheControl ) {
			// conservative by default
			return 'private, must-revalidate';
		}
		
		$header = $this->getCacheControlHeader();
		if( isset( $this->cacheControl['public'] ) || isset( $this->cacheControl['private'] ) ) {
			return $header;
		}
		
		// public if s-maxage is defined, private otherwise
		if( !isset( $this->cacheControl['s-maxage'] ) ) {
			return $header . ', private';
		}
		
		return $header;
	}
}